package com.itheima.sfbx.insurance.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.sfbx.framework.commons.constant.basic.SuperConstant;
import com.itheima.sfbx.framework.commons.constant.insure.InsureConstant;
import com.itheima.sfbx.framework.commons.dto.basic.TreeItemVO;
import com.itheima.sfbx.framework.commons.dto.basic.TreeVO;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.NoProcessing;
import com.itheima.sfbx.insurance.dto.CategoryCoefficentVO;
import com.itheima.sfbx.insurance.dto.CategoryConditionVO;
import com.itheima.sfbx.insurance.dto.CategorySafeguardVO;
import com.itheima.sfbx.insurance.dto.CategoryVO;
import com.itheima.sfbx.insurance.mapper.CategoryMapper;
import com.itheima.sfbx.insurance.pojo.Category;
import com.itheima.sfbx.insurance.pojo.CategoryCoefficent;
import com.itheima.sfbx.insurance.pojo.CategoryCondition;
import com.itheima.sfbx.insurance.pojo.CategorySafeguard;
import com.itheima.sfbx.insurance.service.ICategoryCoefficentService;
import com.itheima.sfbx.insurance.service.ICategoryConditionService;
import com.itheima.sfbx.insurance.service.ICategorySafeguardService;
import com.itheima.sfbx.insurance.service.ICategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description：保险分类服务实现类
 */
@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {

    @Autowired
    ICategoryConditionService categoryConditionService;

    @Autowired
    ICategoryCoefficentService categoryCoefficentService;

    @Autowired
    ICategorySafeguardService categorySafeguardService;


    private LambdaQueryWrapper<Category> queryWrapper(CategoryVO categoryVO) {
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StrUtil.isNotBlank(categoryVO.getParentCategoryNo()), Category::getParentCategoryNo, categoryVO.getParentCategoryNo())
                .eq(StrUtil.isNotBlank(categoryVO.getCategoryNo()), Category::getCategoryNo, categoryVO.getCategoryNo())
                .like(StrUtil.isNotBlank(categoryVO.getCategoryName()), Category::getCategoryName, categoryVO.getCategoryName())
                .eq(StrUtil.isNotBlank(categoryVO.getCategoryName()), Category::getCategoryName, categoryVO.getCategoryName())
                .eq(StrUtil.isNotBlank(categoryVO.getCategoryType()), Category::getCategoryType, categoryVO.getCategoryType())
                .eq(StrUtil.isNotEmpty(categoryVO.getDataState()), Category::getDataState, categoryVO.getDataState())
                .eq(StrUtil.isNotBlank(categoryVO.getLeafNode()), Category::getLeafNode, categoryVO.getLeafNode())
                .eq(StrUtil.isNotBlank(categoryVO.getShowIndex()), Category::getShowIndex, categoryVO.getShowIndex());

        return wrapper;
    }

    /**
     * 构建VO列表
     *
     * @param categoryVOList
     */
    private void buildVoList(List<CategoryVO> categoryVOList) {
        //查询关联项
        Set<String> noSet = categoryVOList.stream().map(CategoryVO::getCategoryNo).collect(Collectors.toSet());


        List<CategoryCondition> categoryConditionList = categoryConditionService.lambdaQuery().in(CategoryCondition::getCategoryNo, noSet).list();
        Map<String, List<CategoryCondition>> conditionMap = categoryConditionList.stream().collect(Collectors.groupingBy(CategoryCondition::getCategoryNo));

        List<CategoryCoefficent> categoryCoefficentList = categoryCoefficentService.lambdaQuery().in(CategoryCoefficent::getCategoryNo, noSet).list();
        Map<String, List<CategoryCoefficent>> coefficentMap = categoryCoefficentList.stream().collect(Collectors.groupingBy(CategoryCoefficent::getCategoryNo));

        List<CategorySafeguard> categorySafeguardList = categorySafeguardService.lambdaQuery().in(CategorySafeguard::getCategoryNo, noSet).list();
        Map<String, List<CategorySafeguard>> safeguardMap = categorySafeguardList.stream().collect(Collectors.groupingBy(CategorySafeguard::getCategoryNo));

        for (CategoryVO vo : categoryVOList) {
            String categoryNo = vo.getCategoryNo();
            vo.setCategoryConditionVOs(BeanConv.toBeanList(conditionMap.get(categoryNo), CategoryConditionVO.class));
            vo.setCategoryCoefficentVOs(BeanConv.toBeanList(coefficentMap.get(categoryNo), CategoryCoefficentVO.class));
            vo.setCategorySafeguardVOs(BeanConv.toBeanList(safeguardMap.get(categoryNo), CategorySafeguardVO.class));
        }
    }

    @Override
    public Page<CategoryVO> findPage(CategoryVO categoryVO, int pageNum, int pageSize) {

//        try {
//            //构建分页对象
//            Page<Category> categoryPage = new Page<>(pageNum, pageSize);
//            //构建查询条件
//            LambdaQueryWrapper<Category> queryWrapper = queryWrapper(categoryVO);
//            //查询分页基本列表数据
//            Page<Category> page = page(categoryPage, queryWrapper);
//            if (EmptyUtil.isNullOrEmpty(page.getRecords())) {
//                return null;
//            }
//            //转换为要返回的VO列表数据
//            Page<CategoryVO> resultPage = BeanConv.toPage(page, CategoryVO.class);
//
//            //获取分类列表的每个分类编号放置到一个集合set中
//            Set<String> categoryNoSet = page.getRecords().stream().map(Category::getCategoryNo).collect(Collectors.toSet());
//
//        /*处理每个分类的保障项:
//        ①根据查询到的分类编号查询出分类下的保障项列表；
//        ②对保障项列表根据分类分组；
//        ③遍历分类列表设置对应的保障项列表
//         */
//            List<CategorySafeguardVO> categorySafeguardVOs = categorySafeguardService.findListInCategoryNo(categoryNoSet);
//            Map<String, List<CategorySafeguardVO>> categorySafeguardVOMap = categorySafeguardVOs.stream().
//                    collect(Collectors.groupingBy(CategorySafeguardVO::getCategoryNo));
//            if (!EmptyUtil.isNullOrEmpty(resultPage.getRecords())) {
//                resultPage.getRecords().forEach(tmpCategoryVO -> {
//                    tmpCategoryVO.setCategorySafeguardVOs(categorySafeguardVOMap.get(tmpCategoryVO.getCategoryNo()));
//                });
//            }
//        /*处理每个分类的系数项:
//        ①根据查询到的分类编号查询出分类下的系数项列表；
//        ②对系数项列表根据分类分组；
//        ③遍历分类列表设置对应的系数项列表
//         */
//            List<CategoryCoefficentVO> categoryCoefficentVOs = categoryCoefficentService.findListInCategoryNo(categoryNoSet);
//            Map<String, List<CategoryCoefficentVO>> categoryCoefficentVOMap = categoryCoefficentVOs.stream().
//                    collect(Collectors.groupingBy(CategoryCoefficentVO::getCategoryNo));
//            if (!EmptyUtil.isNullOrEmpty(resultPage.getRecords())) {
//                resultPage.getRecords().forEach(tmpCategoryVO -> {
//                    tmpCategoryVO.setCategoryCoefficentVOs(categoryCoefficentVOMap.get(tmpCategoryVO.getCategoryNo()));
//                });
//            }
//        /*处理每个分类的筛选项:
//        ①根据查询到的分类编号查询出分类下的筛选项列表；
//        ②对筛选项列表根据分类分组；
//        ③遍历分类列表设置对应的筛选项列表
//         */
//            List<CategoryConditionVO> categoryConditionVOs = categoryConditionService.findListInCategoryNo(categoryNoSet);
//            Map<String, List<CategoryConditionVO>> categoryConditionVOMap = categoryConditionVOs.stream().
//                    collect(Collectors.groupingBy(CategoryConditionVO::getCategoryNo));
//            if (!EmptyUtil.isNullOrEmpty(resultPage.getRecords())) {
//                resultPage.getRecords().forEach(tmpCategoryVO -> {
//                    tmpCategoryVO.setCategoryConditionVOs(categoryConditionVOMap.get(tmpCategoryVO.getCategoryNo()));
//                });
//            }
//
//            //返回结果
//            return resultPage;
//        } catch (Exception e) {
//            log.error("保险分类分页查询异常：{}", ExceptionsUtil.getStackTraceAsString(e));
//            throw new ProjectException(CategoryEnum.PAGE_FAIL);
//        }
        LambdaQueryWrapper<Category> lqw = queryWrapper(categoryVO);
        Page<Category> categoryPage = this.page(new Page<>(pageNum, pageSize), lqw);
        //转化
        Page<CategoryVO> categoryVOPage = BeanConv.toPage(categoryPage, CategoryVO.class);

        List<CategoryVO> categoryVOList = categoryVOPage.getRecords();
        if (CollUtil.isEmpty(categoryVOList)) {
            return categoryVOPage;
        }
        buildVoList(categoryVOList);
        return categoryVOPage;
    }


    @Override
    @Transactional
    public CategoryVO save(CategoryVO categoryVO) {
        Category category = BeanConv.toBean(categoryVO, Category.class);
        //因为前端不会传递CategoryNo，所以需要自己生成一个
        String head = NoProcessing.processString(category.getParentCategoryNo());
        Category one = this.lambdaQuery()
                .like(Category::getCategoryNo, head)
                .orderByDesc(Category::getCategoryNo)
                .last("limit 1")
                .one();
        String no = NoProcessing.createNo(one.getCategoryNo(), true);
        category.setCategoryNo(no);
        save(category);
        return BeanConv.toBean(category, CategoryVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(CategoryVO categoryVO) {
        //先修改自己
        Category category = BeanConv.toBean(categoryVO, Category.class);
        this.updateById(category);

        //先删除全部关联关系
        categoryConditionService.deleteByCategoryNo(category.getCategoryNo());
        categoryCoefficentService.deleteByCategoryNo(category.getCategoryNo());
        categorySafeguardService.deleteByCategoryNo(category.getCategoryNo());
        //再添加关联关系
        List<CategoryConditionVO> categoryConditionVOs = categoryVO.getCategoryConditionVOs();
        List<CategoryCoefficentVO> categoryCoefficentVOs = categoryVO.getCategoryCoefficentVOs();
        List<CategorySafeguardVO> categorySafeguardVOs = categoryVO.getCategorySafeguardVOs();
        if (CollUtil.isNotEmpty(categoryConditionVOs)) {
            categoryConditionVOs.forEach(n->{n.setCategoryNo(category.getCategoryNo());});
            categoryConditionService.saveBatch(BeanConv.toBeanList(categoryConditionVOs, CategoryCondition.class));
        }
        if (CollUtil.isNotEmpty(categoryCoefficentVOs)) {
            categoryCoefficentVOs.forEach(n->{n.setCategoryNo(category.getCategoryNo());});
            categoryCoefficentService.saveBatch(BeanConv.toBeanList(categoryCoefficentVOs, CategoryCoefficent.class));
        }
        if (CollUtil.isNotEmpty(categorySafeguardVOs)) {
            categorySafeguardVOs.forEach(n->{n.setCategoryNo(category.getCategoryNo());});
            categorySafeguardService.saveBatch(BeanConv.toBeanList(categorySafeguardVOs, CategorySafeguard.class));
        }
        return true;
    }

    @Override
    @Transactional
    public Boolean delete(String[] checkedIds) {
        List<String> idList = Arrays.stream(checkedIds).collect(Collectors.toList());
        List<Category> categoryList = this.lambdaQuery()
                .eq(Category::getId, idList)
                .list();
        List<String> collect = categoryList.stream().map(Category::getCategoryNo).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect)) {
            //删除分类
            this.removeByIds(idList);
            //删除分类下的系数项
            categoryCoefficentService.deleteByCategoryNos(collect);
            //删除分类下的筛选项
            categoryConditionService.deleteByCategoryNos(collect);
            //删除分类下的保障项
            categorySafeguardService.deleteByCategoryNos(collect);
        }
        return true;
    }

    @Override
    public List<CategoryVO> findList(CategoryVO query) {
        LambdaQueryWrapper<Category> lqw = queryWrapper(query);
        List<Category> categoryList = this.list(lqw);
        List<CategoryVO> categoryVOList = BeanConv.toBeanList(categoryList, CategoryVO.class);
        //处理层级
        List<Long> nodeFloors = query.getNodeFloors();
        if (CollUtil.isEmpty(categoryVOList)) {
            return new ArrayList<>();
        }
        if (CollUtil.isNotEmpty(nodeFloors)) {
            categoryVOList = categoryVOList.stream().filter(x -> {
                Long level = (long) (NoProcessing.processString(x.getCategoryNo()).length() / 3 - 1);
                return nodeFloors.contains(level);
            }).collect(Collectors.toList());
            buildVoList(categoryVOList);
        }
        return categoryVOList;
    }


    @Override
    public TreeVO categoryTreeVO(String parentCategoryNo, String categoryType, String[] checkedCategoryNos) {

        //1.找根节点
        String rootNo = StrUtil.isEmpty(parentCategoryNo) ? SuperConstant.ROOT_PARENT_ID : parentCategoryNo;
        //2.找根节点下的所有子节点
        String head = NoProcessing.processString(rootNo);
        //自己也要查出来
        //select * from category where category_no like ? and category_type = ?
        List<Category> list = this.lambdaQuery()
                .likeRight(Category::getCategoryNo, head)
                .eq(StrUtil.isNotEmpty(categoryType), Category::getCategoryType, categoryType)
                .list();
        if (CollUtil.isEmpty(list)) {
            //如果为空,说明前端传的参数有问题,就算没有子节点也要查到自己本身,不可能是空
            log.error("查询失败,{}有问题", parentCategoryNo);
        }
        //转化对象类型
        List<TreeItemVO> treeItemVOList = list.stream().map(x ->
                TreeItemVO.builder()
                        .id(x.getCategoryNo())
                        .parentId(x.getParentCategoryNo())
                        .label(x.getCategoryName())
                        .build()
        ).collect(Collectors.toList());
        //3.构建树形结构
        //3.1 聚合为map,利用父节点id做key,value是子节点集合
        Map<String, List<TreeItemVO>> pidMap = treeItemVOList.stream().collect(Collectors.groupingBy(TreeItemVO::getParentId));
        //遍历封装树形结构
        for (TreeItemVO treeItemVO : treeItemVOList) {
            //找到当前节点的子节点,从map中取出来,存入children
            List<TreeItemVO> children = pidMap.get(treeItemVO.getId());
            treeItemVO.setChildren(children);
        }
        return TreeVO.builder()
                .items(pidMap.get(rootNo))
                .build();
    }

    @Override
    public String createCategoryNo(String parentCategoryNo) {
        CategoryVO categoryVO = CategoryVO.builder()
                .parentCategoryNo(parentCategoryNo)
                .build();
        QueryWrapper<Category> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Category::getParentCategoryNo, parentCategoryNo);
        List<Category> categoryList = list(queryWrapper);
        //无下属节点则创建下属节点
        if (EmptyUtil.isNullOrEmpty(categoryList)) {
            return NoProcessing.createNo(parentCategoryNo, false);
            //有下属节点则累加下属节点
        } else {
            Long categoryNo = categoryList.stream()
                    .map(category -> {
                        return Long.valueOf(category.getCategoryNo());
                    })
                    .max(Comparator.comparing(i -> i)).get();
            return NoProcessing.createNo(String.valueOf(categoryNo), true);
        }
    }

    /**
     * 人种榜险种榜分类
     *
     * @param type
     */
    @Override
    public List<CategoryVO> categoryCheckRule(String type) {
        //判断是否是险种榜
        if (InsureConstant.checkIsInsureType(type)) {
            List<CategoryVO> res = new ArrayList<>();
            //获取所有的险种榜
            List<String> allCheckRule = InsureConstant.getAllCheckRule();
            allCheckRule.forEach(e -> {
                CategoryVO categoryVO = CategoryVO.builder().categoryNo(e).categoryName(InsureConstant.getRuleNameById(e)).build();
                res.add(categoryVO);
            });
            return res;
        } else {
            //说明是人种榜
            List<String> categoryNames = Arrays.asList("成年人", "少儿", "老人");
            LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(Category::getCategoryName, categoryNames);
            queryWrapper.eq(Category::getDataState, SuperConstant.DATA_STATE_0);
            List<CategoryVO> res = BeanConv.toBeanList(list(queryWrapper), CategoryVO.class);
            return res;
        }
    }
}
